export class TextInterpreter {
    /**
     * @param {string} text 
     * @param {number} start
     * @return {{
     * nexti,
     * endi,
     * type,
     * failed,
     * layerCount,
     * value}}
     */
    static parse(text, start) {
        let len = text.length
        let phase = 0;
        let symbol = '';
        let nBegin = 0;
        let nEnd = 0;
        let testLayerCount = 0;
        let complete = false;
        let state = {
            nexti: start + 1,
            endi: null,
            type: '',
            failed: false,
            layerCount: 0,
            value: 0
        };
        for (let i = start; i < len; ++i) {
            symbol = text[i];
            if (phase == 0) {
                if (symbol == '\\') {
                    phase = 2;
                } else {
                    state.failed = true;
                    break;
                }
            } else if (phase == 1) {
                if (symbol == '\\') {
                    phase = 2;
                } else if (symbol >= '0' && symbol <= '9') {
                    phase = 4;
                    nBegin = i;
                    nEnd = i;
                    --i;
                } else {
                    state.failed = true;
                    state.nexti = i - 1;
                    break;
                }
            } else if (phase == 2) {
                if (state.type) {
                    if (symbol != 'V') {
                        state.type = '';
                        state.failed = true;
                        state.nexti = i - 2;
                        break;
                    } else {
                        phase = 3;
                    }
                } else {
                    switch (symbol) {
                        case 'V':
                        case 'C':
                        case 'I':
                            phase = 3;
                        case '{':
                        case '}':
                            state.type = symbol;
                            break;
                        default:
                            state.failed = true;
                            break;
                    }

                    if (symbol == '{' || symbol == '}' || state.failed) {
                        complete = true;
                        state.nexti = state.failed ? i - 1 : i;
                        break;
                    }
                }
            } else if (phase == 3) {
                if (symbol == '[') {
                    phase = 1;
                    ++state.layerCount;
                    ++testLayerCount;
                } else {
                    state.nexti = i - 1;
                    state.failed = true;
                    break;
                }
            } else if (phase == 4) {
                if (symbol < '0' || symbol > '9') {
                    phase = 5;
                    --i;
                } else {
                    ++nEnd;
                }
            } else if (phase == 5) {
                if (symbol == ']') {
                    --testLayerCount;
                    //[] ]]
                    if (testLayerCount <= 0) {
                        state.nexti = i;
                        state.endi = nBegin - state.layerCount * 3;
                        state.value = Number(text.slice(nBegin, nEnd));
                        complete = true;
                        break;
                    }
                } else {
                    complete = true;
                    state.nexti = i - 1;
                    //[[b ]_
                    if (testLayerCount > 0) {
                        //[[b...e
                        if (testLayerCount == state.layerCount) {
                            state.failed = true;
                        } else {
                            //[\C[\T[]]_
                            state.type = 'V';
                            state.layerCount -= testLayerCount;
                            state.endi = nBegin - state.layerCount * 3;
                            state.value = Number(text.slice(nBegin, nEnd));
                        }
                    }
                    break;
                }
            }
        }

        if (!complete && !state.failed) {
            state.nexti = len - 1;
            if (state.layerCount != testLayerCount) {
                state.type = 'V';
                state.layerCount -= testLayerCount;
                state.endi = nBegin - state.layerCount * 3;
                state.value = Number(text.slice(nBegin, nEnd));
            } else {
                state.failed = true;
            }
        }

        return state;
    }

    static DismantleVariables(state){
        let value=state.value;
        let layerCount=state.layerCount-1;
        while(layerCount>0){
            value=$gameVariables.value(value);
            --layerCount;
        }
        return value;
    }

}